話不多說,直接進入主題...
前一篇有提到,在多國語系 vue-i18n-next
應用篇主要分享幾個主題:
Pinia
記憶使用者選擇語系 - localStorage
Loco
Google 試算表
管理語言包評估內容很像會太多,但是對於前端管理語言包真的很實用,只是自己實作上比較常使用是第一項和第三項,第二項的後半部因為對 Node.js 不熟悉,相關原理也就是為什麼語法可以這樣下,可能還需要再研究...,所以附上相關參考資料,未來把 Node.js 觀念補足後再回來這裡寫補充。
Pinia
記憶使用者選擇語系 - localStorage
同樣身為使用者會希望自己造訪某個網頁已經選擇語系,之後再次回訪能夠不用再重新選擇,此時可以使用 localStorage
(網頁資料庫)。
(資料來源:Window.localStorage)
(本機查詢方法:可以開啟 chrome 開發者工具的
Application
看到有 3 個瀏覽器網頁資料庫。)
以上是基本的介紹,簡單來說:就是一個存取資料的一個地方,假設今天在 A 網頁用 setItem
存入資料,可以在其他網頁用 getItem
,直到碰到程式碼有 removeItem
或是 clear
,才會消失不見,更多詳細內容可以用關鍵字 localStorage 查詢。
接下來就要試著用 localStorage
的特性記憶使用者的語言選擇,這裡使用下拉式選單當作語言切換觸發點:
在 store
中做語言包的狀態管理:
Pinia
主要是因為 i18n
主要是針對本地且不會動態變化的項目像 <header>…</header>
、 <footer>…</footer>
內容較為固定的設定,如果要把內容也轉換,通常會透過傳參數的方法或是讓 url 夾帶給 api 請後端幫忙回傳,此時如果有一個共用的地方就不需要一直用 getItem
取得 localStorage
資料。// src/store/index.js
import { defineStore } from "pinia";
import { reactive } from "vue";
export const useLangStore = defineStore('language', () => {
const stateInit = reactive({
langsOption: [
{
id: 0,
key: "zh-TW",
title: "繁體中文",
},
{
id: 1,
key: "en-US",
title: "English(United States)",
},
{
id: 2,
key: "ja-JP",
title: "日本語",
},
],
currentLang: null
})
return { stateInit }
})
定義語言包內容:
// src/i18n/common.json
{
"zh-TW": {
"welcome": "你好世界"
},
"ja-JP": {
"welcome": "こんにちは世界"
},
"en-US": {
"welcome": "Hello World"
}
}
建立 vue-i18n-next
:在默認語言中先取得 localStorage
的紀錄
localStorage
紀錄流程:F12 → Application
→ localStorage
// src/i18n/i18n.js
import { createI18n } from "vue-i18n";
import message from "./common.json";
const i18n = new createI18n({
legacy: false, // 啟用新的 Vue3 選項
locale: localStorage.getItem('lang') ?? "zh-TW", // 設置默認語言
messages: message,
fallbackLocale: "zh-TW",
});
export { i18n };
在 main.js
引入 vue-i18n-next
import { i18n } from "@/i18n/i18n";
import { createApp } from 'vue';
import { createPinia } from 'pinia';
import App from './App.vue';
import router from './router';
const app = createApp(App);
const pinia = createPinia();
app.use(i18n);
app.use(pinia);
app.use(router);
app.mount('#app');
在 .vue 元件
中引入:
setItem
記錄使用者的選擇,並且同步到 Pinia
import { watch } from 'vue';
import { useI18n } from 'vue-i18n';
import { useLangStore } from '@/stores/index.js';
const { locale } = useI18n();
const langStore = useLangStore();
langStore.stateInit.currentLang = locale.value;
watch(locale, (newLocale) => {
langStore.stateInit.currentLang = newLocale;
localStorage.setItem('lang', newLocale);
})
<div class="my-5">
<select class="form-select w-25" v-model="locale">
<option
v-for="(lang, i) in langStore.stateInit.langsOption"
:key="`Lang${i}${lang.id}`"
:value="lang.key"
>
{{ lang.title }}
</option>
</select>
<p class="text-primary">{{ $t('welcome') }}</p>
</div>
畫面展示:
Loco
前面有提到, i18n
很好用但是如果只能在本地新增編輯語言包真的不太方便,而且量很大,如果是自己的專案可以在現有的 api 新增 key 分離不同語系的翻譯包,但是協同開發呢?
如果有工具可以統一管理其實是前端一大福音,研究 i18n
過程發現 RexHung's Blog 分享的 Loco 開發人員翻譯管理。
官網文件:Translation Management for Developers
https://localise.biz/
以下是對於這個網站的註冊使用流程,建立完成後的一鍵更新語言包,個人建議詳細資料可以參考這篇「[Vue Note] — 在 Vue3 優雅的引入 I18n 之餘,透過網站統一管理並一鍵更新」的後半段
Asset ID
輸入要設定的語系 Key,這邊先測試輸入 welcome。New locale
,再度點擊後會彈出一個視窗,這時候就可以輸入你想新增的語系了,但記得,語系越多,佔用的 Translation 就會越多!
API Key
:記得請使用上方的,下方的會包含可以修改的權限,這邊不需要用到
。GET /api/export/all.{ext}
這支 API。Node.js
建立在 Loco
中建立的語言檔npm install axios fs
創建一個名為 updateLocales.js
的腳本文件
const axios = require('axios');
const fs = require('fs');
// Loco API 設置
const LOCO_API_KEY = 'pEeDnRydTNs_vVLSIh_KyK3?????????'; // 替換為 Loco API 密鑰
const LOCO_PROJECT_ID = 'test'; // 替換為 Loco 專案 ID
const LOCO_EXPORT_FORMAT = 'json'; // 語言包導出格式 JSON
// 目標本地化文件目錄
const LOCALES_DIR = './src/locales'; // 替換為本地化文件存放目錄
// 語言列表
const LANGUAGES = ['zh-TW', 'ja-JP', 'en-US']; // 替換為語言列表
// Loco API 請求頭
const axiosInstance = axios.create({
baseURL: `https://localise.biz/api/export/locale/${LOCO_EXPORT_FORMAT}`,
headers: {
Authorization: `Loco ${LOCO_API_KEY}`,
},
});
// 下載並更新語言包
async function updateLocales() {
try {
for (const lang of LANGUAGES) {
const response = await axiosInstance.get(`/${LOCO_PROJECT_ID}/${lang}`);
const localeData = response.data;
// 將語言包保存到本地文件
const filePath = `${LOCALES_DIR}/${lang}.json`;
fs.writeFileSync(filePath, JSON.stringify(localeData, null, 2), 'utf8');
console.log(`Updated ${lang}.json`);
}
console.log('Localization files updated successfully.');
} catch (error) {
console.error('Error updating localization files:', error);
}
}
// 執行更新語言包操作
updateLocales();
updateLocales.js
,再需要時運行腳本就會更新。
node updateLocales.js
Google 試算表
管理語言包因為研究上一個方法其實耗了不少時間,在研究成功之前,其實主要用 2 種方法轉換:
JSON-server
建立客製化資料庫 (如果有現成的 API 可以打,也可以用 POST /posts
的方法丟翻譯物件到資料庫Mike 的流程寫得很清楚,還有附上 google API 金鑰申請流程,需要的夥伴可以多加參考!
今天要另外分享的是六角學院 2023-09-07 舉辦線上分享會「利用前端解決多國語系專案維護的種種難題 - 教你如何提升跨國團隊的協作效率 by Unabiz Neil , Zoie」
內容提到:翻譯師可能去修改語言表達內容,告知開發需要一個一個比對並且複製貼上去修改,這實在太辛苦,如果有工具可以大家一起維護還有防呆機制或許是很好的選擇,講師主要分享 google 試算表的方法,詳細可以上 github 看一下,目前還沒有 npm 安裝,有許願希望能實現,這樣也可以少很多工。
利用前端解決多國語系專案維護的種種難題,教你如何提升跨國團隊的協作效率
https://github.com/neil585456525/i18n-google-sheet-example
個人目前使用第一種和第三種的方法混打,或許 Neil 大大有 npm 安裝後,就可以再更方便使用語系轉換,期待願望成真